package com.gzc.just.play.last.war.allinone.orchestration;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import jakarta.annotation.PostConstruct;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 服务器状态管理器
 * 跟踪服务器启动状态和端口监听状态
 */
@Component
public class ServerStateManager {
    
    private static final Logger logger = LoggerFactory.getLogger(ServerStateManager.class);
    
    @Autowired
    private ApplicationContext applicationContext;
    
    private final Map<ServerType, ServerState> serverStates = new ConcurrentHashMap<>();
    private final Map<ServerType, Object> serverBeans = new ConcurrentHashMap<>();
    private final Map<ServerType, Long> stateChangeTimestamps = new ConcurrentHashMap<>();
    
    /**
     * 状态变更监听器
     */
    public interface StateChangeListener {
        void onStateChange(ServerType serverType, ServerState oldState, ServerState newState);
    }
    
    private StateChangeListener stateChangeListener;
    
    /**
     * 初始化状态管理器
     */
    @PostConstruct
    public void initialize() {
        logger.info("Initializing server state manager...");
        
        // 初始化所有服务器状态为UNINITIALIZED
        for (ServerType serverType : ServerType.values()) {
            serverStates.put(serverType, ServerState.UNINITIALIZED);
            stateChangeTimestamps.put(serverType, System.currentTimeMillis());
        }
        
        // 加载服务器Bean
        loadServerBeans();
        
        logger.info("Server state manager initialized with {} servers", ServerType.values().length);
    }
    
    /**
     * 加载服务器Bean
     */
    private void loadServerBeans() {
        // 根据服务器类型加载对应的Bean
        serverBeans.put(ServerType.LOGIN_SERVER, getServerBean("loginNettyServer"));
        serverBeans.put(ServerType.BALANCE_SERVER, getServerBean("balanceNettyServer"));
        serverBeans.put(ServerType.CENTRAL_SERVER, getServerBean("central-centralNettyServer"));
        serverBeans.put(ServerType.GATE_SERVER, getServerBean("gateNettyServer"));
        serverBeans.put(ServerType.SCENE_SERVER, getServerBean("sceneNettyServer"));
    }
    
    /**
     * 获取服务器Bean
     * @param beanName Bean名称
     * @return 服务器Bean实例
     */
    private Object getServerBean(String beanName) {
        try {
            return applicationContext.getBean(beanName);
        } catch (Exception e) {
            logger.warn("Server bean not found: {}", beanName, e);
            return null;
        }
    }
    
    /**
     * 设置状态变更监听器
     * @param listener 监听器
     */
    public void setStateChangeListener(StateChangeListener listener) {
        this.stateChangeListener = listener;
    }
    
    /**
     * 获取服务器状态
     * @param serverType 服务器类型
     * @return 当前状态
     */
    public ServerState getServerState(ServerType serverType) {
        return serverStates.get(serverType);
    }
    
    /**
     * 获取所有服务器状态
     * @return 服务器状态映射
     */
    public Map<String, ServerState> getAllServerStates() {
        Map<String, ServerState> result = new ConcurrentHashMap<>();
        serverStates.forEach((serverType, state) -> 
            result.put(serverType.getName(), state));
        return result;
    }
    
    /**
     * 更新服务器状态
     * @param serverType 服务器类型
     * @param newState 新状态
     * @return 是否成功更新
     */
    public boolean updateServerState(ServerType serverType, ServerState newState) {
        ServerState oldState = serverStates.get(serverType);
        
        if (oldState == newState) {
            return true;
        }
        
        // 验证状态转换是否合法
        if (!isValidStateTransition(oldState, newState)) {
            logger.warn("Invalid state transition for {}: {} -> {}", 
                      serverType.getName(), oldState, newState);
            return false;
        }
        
        serverStates.put(serverType, newState);
        stateChangeTimestamps.put(serverType, System.currentTimeMillis());
        
        logger.info("Updated server state: {} {} -> {}", 
                   serverType.getName(), oldState, newState);
        
        // 通知监听器
        if (stateChangeListener != null) {
            try {
                stateChangeListener.onStateChange(serverType, oldState, newState);
            } catch (Exception e) {
                logger.error("Error in state change listener", e);
            }
        }
        
        return true;
    }
    
    /**
     * 检查状态转换是否合法
     * @param oldState 旧状态
     * @param newState 新状态
     * @return 是否合法
     */
    private boolean isValidStateTransition(ServerState oldState, ServerState newState) {
        // 错误状态可以转换到任何状态
        if (oldState == ServerState.ERROR) {
            return true;
        }
        
        switch (oldState) {
            case UNINITIALIZED:
                return newState == ServerState.INITIALIZING;
                
            case INITIALIZING:
                return newState == ServerState.INITIALIZED || newState == ServerState.ERROR;
                
            case INITIALIZED:
                return newState == ServerState.STARTING;
                
            case STARTING:
                return newState == ServerState.LISTENING || newState == ServerState.ERROR;
                
            case LISTENING:
                return newState == ServerState.CONNECTING || newState == ServerState.ERROR;
                
            case CONNECTING:
                return newState == ServerState.CONNECTED || newState == ServerState.ERROR;
                
            case CONNECTED:
                return newState == ServerState.READY || newState == ServerState.ERROR;
                
            case READY:
                return newState == ServerState.RUNNING || newState == ServerState.ERROR;
                
            case RUNNING:
                return newState == ServerState.STOPPING;
                
            case STOPPING:
                return newState == ServerState.STOPPED;
                
            case STOPPED:
                return true; // 可以重新启动
                
            case UNHEALTHY:
                return newState == ServerState.RUNNING || newState == ServerState.ERROR;
                
            default:
                return false;
        }
    }
    
    /**
     * 获取服务器Bean
     * @param serverType 服务器类型
     * @return 服务器Bean实例
     */
    public Object getServerBean(ServerType serverType) {
        return serverBeans.get(serverType);
    }
    
    /**
     * 检查服务器是否准备就绪
     * @param serverType 服务器类型
     * @return 是否准备就绪
     */
    public boolean isServerReady(ServerType serverType) {
        ServerState state = serverStates.get(serverType);
        return state == ServerState.READY || state == ServerState.RUNNING;
    }
    
    /**
     * 检查服务器是否正在运行
     * @param serverType 服务器类型
     * @return 是否正在运行
     */
    public boolean isServerRunning(ServerType serverType) {
        ServerState state = serverStates.get(serverType);
        return state == ServerState.RUNNING || 
               state == ServerState.CONNECTED || 
               state == ServerState.READY;
    }
    
    /**
     * 检查服务器是否发生错误
     * @param serverType 服务器类型
     * @return 是否发生错误
     */
    public boolean isServerError(ServerType serverType) {
        ServerState state = serverStates.get(serverType);
        return state == ServerState.ERROR || state == ServerState.UNHEALTHY;
    }
    
    /**
     * 停止所有服务器
     */
    public void stopAllServers() {
        logger.info("Stopping all servers...");
        
        for (ServerType serverType : ServerType.values()) {
            if (isServerRunning(serverType)) {
                updateServerState(serverType, ServerState.STOPPING);
            }
        }
        
        // 这里应该调用实际的服务器停止逻辑
        // 例如，通过反射调用服务器Bean的停止方法
    }
    
    /**
     * 获取状态变更时间戳
     * @param serverType 服务器类型
     * @return 时间戳
     */
    public long getStateChangeTimestamp(ServerType serverType) {
        return stateChangeTimestamps.get(serverType);
    }
    
    /**
     * 获取状态持续时间
     * @param serverType 服务器类型
     * @return 持续时间（毫秒）
     */
    public long getStateDuration(ServerType serverType) {
        Long timestamp = stateChangeTimestamps.get(serverType);
        return timestamp != null ? System.currentTimeMillis() - timestamp : 0;
    }
}